package to52.android.services;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import to52.android.database.RetreiveData;
import to52.android.screens.MainScreen;

import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import fr.utbm.network.IdentificationMessage;
import fr.utbm.network.PatientListMessage;
import fr.utbm.network.SimpleMessage;

/**
 * 
 * C'est ce service qui a la socket de communication et qui envoi et reçoit les
 * messages du serveur
 * 
 */

public class PullService extends Service {

	/**
	 * Port utilisé sur le serveur
	 */
	private static final int port = 8081;

	/**
	 * Adresse du serveur
	 */
	private static String IPServer = "";


	/**
	 * Instance du service
	 */
	private static PullService m_instance = null;

	/**
	 * La socket de communcation avec le serveur
	 */
	Socket m_socket;
	
	private static Activity activity = null;

	/**
	 * Flux de sortie
	 */
	private ObjectOutputStream m_out;

	/**
	 * Flux d'entrée
	 */
	private ObjectInputStream m_in;

	
	private Handler handler;
	
	/**
	 * Obtient l'instance du service
	 */
	public static PullService getInstance() {
		return m_instance;
	}
	
	public static void killInstance() {
		m_instance = null;
	}
	
	public static void setActivity(Activity act) {
		activity = act;
	}
	
	@Override
	public void onCreate() {
		Log.d(this.getClass().getName(), "Création du service");
		super.onCreate();
		handler = new Handler(Looper.getMainLooper());
		m_socket = null;
		m_instance = this;
	}

	/**
	 * Le corps du service
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(this.getClass().getName(), "Service launched");

		//final Context context = this;
		
		// passe en thread car readline est bloquant
		Thread t = new Thread(new Runnable() {

			public void run() {
				
				IPServer = getIPServer();

				//while (true) {

					Log
							.d(this.getClass().getName(),
									"Création de la socket...");
					try {
						m_socket = new Socket(IPServer, port);
						m_out = new ObjectOutputStream(m_socket
								.getOutputStream());
						m_in = new ObjectInputStream(m_socket.getInputStream());
						Log.d(this.getClass().getName(),
								"La socket a bien été créée !");
					} catch (Exception e) {
						Log.d(this.getClass().getName(),
								"Erreur lors de la création de la socket : "
										+ e.getMessage());
						m_socket = null;					
					}

					sendIdentification();
					getPatientList();
					

					try {
						boolean continuer = true;
						while (continuer) {

							final Object message = m_in.readObject();
							
							Log.d("mess", "Message");

							if (message instanceof SimpleMessage) {
								
								if (!((SimpleMessage) message).getContent().equals("Auth ok")) {
									continuer = false;
								}
								
								// just display the message content
								handler.post(new Runnable() {
									public void run() {
										Toast.makeText(getApplicationContext(), ((SimpleMessage)message).getContent(), Toast.LENGTH_LONG).show();
									}
								});
								
								
							} 
							else {
								if (message instanceof PatientListMessage) {
									PatientListMessage plm = (PatientListMessage) message;
									Log.d("mess", "PatientListMessage");
									if (plm.getPatientList() != null &&
											plm.getPatientList().size() > 0) {
										Log.d("mess", "Size : " + plm.getPatientList().size());
										Log.d("mess", "Patient name : " + 
											plm.getPatientList().get(0).getProfil_nom());
										
										RetreiveData rd = new RetreiveData(activity);
										rd.insertDatasFromSync(plm.getPatientList());
										//RetreiveData.setPatients(plm.getPatientList());
										
										Log.d("mess", "Size : " + RetreiveData.patients.size());
										Log.d("mess", "Patient name : " + 
												RetreiveData.patients.get(0).getProfil_nom());
										
										continuer = false;
										
										handler.post(new Runnable() {
											public void run() {
												Toast.makeText(getApplicationContext(),
													"Sync is ok", 
													Toast.LENGTH_LONG).show();
											}
										});
										
									}
									else {
										Log.d("mess", "No message1");
									}
								}
								
								
								else {
									Log.d("mess", "No message2");
								}
							}
							

						}
					} catch (Exception e) {
						Log.d(this.getClass().getName(),
								"Erreur pendant l'execution du service : " + e.getMessage());
					} finally {
						try {
							if (m_out != null && m_in != null) {
								m_out.close();
								m_in.close();
							}
							if (m_socket != null)
								m_socket.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					// il y a eu une erreur, on va donc attendre un peu avant de
					// tenter une reconnexion
					/*try {
						//Thread.sleep(5000);
					} catch (InterruptedException e) {
					}*/
				//}
					
					// On tue l'instance du thread
					stopSelf();
					MainScreen.killPullService();
					
			}
		});

		t.start();
		
		return START_NOT_STICKY;
	}

	/**
	 * Envoi l'identification au serveur, c'est à dire le numéro de téléphone
	 */
	public static synchronized void sendIdentification() {
		PullService ps = getInstance();

		if (ps.m_socket == null) {
			/*Toast.makeText(ps.getApplicationContext(),
			 "Impossible de se connecter au serveur",
			 Toast.LENGTH_LONG).show();*/
			return;
		}
		
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ps.getApplicationContext());
		String login    = prefs.getString("login", "");
		String password = prefs.getString("password", "");
		
		IdentificationMessage im = new IdentificationMessage(login, password);
		
		try {
			ps.m_out.writeObject(im);
		} catch (IOException e) {
			Log.e("to", "Cannot login (writeObject error)");
		}
	}
	
	public synchronized void getPatientList() {
		PullService ps = getInstance();
		if (ps.m_socket == null) {
			handler.post(new Runnable() {
				public void run() {
					Toast.makeText(getApplicationContext(),
							"Impossible de se connecter au serveur",
							Toast.LENGTH_LONG).show();
				}
			});
			return;
		}
		PatientListMessage plm = new PatientListMessage(null);
		//plm.setPatientList(RetreiveData.patients);
		try {
			ps.m_out.writeObject(plm);
		} catch (IOException e) {
			Log.e("to", "Cannot get patient list (writeObject error)");
		}
	}

	@Override
	public void onDestroy() {
		Log.d(this.getClass().getName(), "Le service est terminé !");
		try {
			if (m_socket != null)
				m_socket.close();
		} catch (IOException e) {
		}
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public static void setIPServer() {
		PullService ps = getInstance();
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ps.getApplicationContext());
		IPServer = prefs.getString("ipAddress", "");
	}
	
	public static String getIPServer() {
		PullService ps = getInstance();
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ps.getApplicationContext());
		return prefs.getString("ipAddress", "");
	}

}
